/**
 * Copyright 2019 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.fos.util;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class JObjectUtils {
    /**
     * 获得字段值
     * 
     * @param field
     * @param target
     * @return
     * @throws Exception
     */
    public static Object getFieldValue(Field field, Object target) throws Exception {
        boolean accessible = field.isAccessible();
        try {
            field.setAccessible(true);
            return field.get(target);
        } finally {
            field.setAccessible(accessible);
        }
    }

    /**
     * 执行方法
     * 
     * @param method
     * @param target
     * @param args
     * @return
     * @throws Exception
     */
    public static Object invokeMethod(Method method, Object target, Object... args) throws Exception {
        boolean accessible = method.isAccessible();
        try {
            method.setAccessible(true);
            return method.invoke(target, args);
        } finally {
            method.setAccessible(accessible);
        }
    }

    /**
     * 复制对象属性
     * 
     * @param from
     * @param to
     * @param skipNull
     */
    public static void copyProperties(Object from, Object to, boolean skipNull) {
        if (from == null || to == null) {
            return;
        }
        Class<?> fromClass = from.getClass();
        Class<?> toClass = to.getClass();
        Method[] methods = toClass.getMethods();
        if (methods != null) {
            for (Method method : methods) {
                String name = method.getName();
                if (name.startsWith("set")) {
                    if (method.getParameterTypes().length != 1) {
                        continue;
                    }
                    String fieldName = name.substring(3);
                    Method readMethod = null;
                    try {
                        readMethod = fromClass.getMethod("get" + fieldName);
                    } catch (NoSuchMethodException e) {
                        try {
                            readMethod = fromClass.getMethod("is" + fieldName);
                        } catch (Exception e1) {
                            continue;
                        }
                    }
                    try {
                        Object value = invokeMethod(readMethod, from);
                        if (value != null || !skipNull) {
                            invokeMethod(method, to, value);
                        }
                    } catch (Exception e) {
                    }
                }
            }
        }
    }

    /**
     * 复制对象属性，通过field设置
     * 
     * @param from
     * @param to
     * @param skipNull
     */
    public static void copyProperties2(Object from, Object to, boolean skipNull) {
        if (from == null || to == null) {
            return;
        }
        Class<?> fromClass = from.getClass();
        Class<?> toClass = to.getClass();
        Field[] fields = toClass.getFields();
        if (fields != null) {
            for (Field field : fields) {
                String name = field.getName();
                String fieldName = name.substring(3);
                Method readMethod = null;
                try {
                    readMethod = fromClass.getMethod("get" + fieldName);
                } catch (NoSuchMethodException e) {
                    try {
                        readMethod = fromClass.getMethod("is" + fieldName);
                    } catch (Exception e1) {
                        continue;
                    }
                }
                try {
                    Object value = invokeMethod(readMethod, from);
                    if (value != null || !skipNull) {
                        field.set(to, value);
                    }
                } catch (Exception e) {
                }
            }
        }
    }

    public static void crossStream(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[512];
        int len = -1;
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
        out.flush();
    }

    public static void close(Closeable closeable) {
        if (closeable == null) {
            return;
        }
        try {
            closeable.close();
        } catch (IOException e) {
        }
    }
}
